home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HyperLib 1997 Winter - Disc 1
/
HYPERLIB-1997-Winter-CD1.ISO.7z
/
HYPERLIB-1997-Winter-CD1.ISO
/
オンラインウェア
/
UTIL
/
ES 1.2 Package.sit
/
ES 1.2 Package
/
Developer’s toolkit
/
ESDemo.c 1.1.1 ƒ
/
ESDemo.c
next >
Wrap
C/C++ Source or Header
|
1995-12-09
|
25KB
|
757 lines
/* ---------------------------------------------------------------------------
ESDemo.c
ゥ1995 Ammon Skidmore, Skidperfect Software Inc. All Rights Reserved.
Freeware: use and borrow whatever code you want for your own modules.
This is a "quick" hack that I threw together to test and demonstrate
Extensions Strip's powerful additions to the Control Strip API. Do not
think that I bothered to optimize anything or that I choose the best methods
to approach each situation. I'd rather waste my time doing that to ES :-)
Key features of this module:
- Fat binary.
- Backward compatibility with Control/Desktop Strip.
- Intelligent drag handling. Under Control/Desktop Strip the draggable
area is the location of the module's icon. Under Extensions Strip this
area is the total amount of space that the module takes up.
- 2 out of the 3 possible methods for sending "safe" AppleEvents that don't rely
upon the front process' context. Under Control/Desktop Strip the event is still
sent, but will not work if the front process does not support Apple Events.
- Ability to get key presses under Extensions Strip without having to install
a custom jGNE filter (as my Key Holder module does.)
- Ability to change the sdevFeatures without having to restart. Examples are
given for changing almost all of the possible features, even locking and
unlocking my sdev code.
- Demonstrates the changing of display height and width.
How to build the FAT module:
- Compile the 68K project first. It will create a clean module (code + what's
in the resource file "ESDemo.オ.rsrc") because the "Merge To File" option is OFF.
- Compile the PPC project last. It will append its code to the module because
the "Merge To File" option is ON. Note that you will have to change the
access paths to allow the project to find the "ExtensionsStripLib" shared library.
Other notes:
- For PPC compiling, remember to use 'weak links' to shared libraries that may not
be on every user's computer. Not doing so will cause a crash because Extensions
Strip will be forced to quit if the library is not present. Modules should use
Gestalt calls to determine the presence of libraries they use.
For example, this project has a weak link to the DragLib, yet it does not have
one to the ExtensionsStripLib or the InterfaceLib because these two libraries
will always be present (PPC ES will not load without the ExtensionsStripLib.)
Version History
-=-=-=-=-=-=-=-
1.0 8/95 - 10/95 - by Ammon Skidmore
30 Oct, 1995 - Made THINK compiler friendly by Vincent Tan.
1.1 9 Nov, 1995 - Added the menu item 'Large Icon' to demonstrate the changing
of display height and width. Also, the icons were slightly
modified, the creator type was changed to '!!!!', and a
'hfdr' resource was added so programs like Conflict Catcher
can look at our info text. Maybe future Finders will display
this balloon help as well...
15 Nov, 1995 - Added Code Warrior 7 projects, by Fran腔is Pottier.
1.1.1 20 Nov, 1995 - Fixed a bug that caused the icon to be drawn incorrectly
when not using Extensions Strip.
- Changed the drag handlers to return dragNotAcceptedErr when
the draw was not accepted, instead of the value -1 as before.
-=-=-=-=-=-=-=-
Framework taken from the CSShell.c Control Strip Sample by Martin R. Wachter.
It is freely availible and can be found on the usual UMich/Info-Mac mirrors.
--------------------------------------------------------------------------- */
#ifdef powerc
// for Metrowerks' linker, this defines the mixed-mode interface for main().
ProcInfoType __procinfo = kPascalStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(long)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
| STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Rect*)))
| STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(WindowRef)));
#endif
#include "ESDemo.h"
#ifndef __GESTALT__
#include <Gestalt.h>
#endif __GESTALT__
#ifndef FALSE
#define FALSE false
#endif
#ifndef TRUE
#define TRUE true
#endif
/******************************************************************************
main: Control Strip's entry point into our sdev code
******************************************************************************/
pascal long main (long message, long params, Rect *statusRect, WindowRef statusPort)
{
register long result = 0L;
switch (message)
{
//
// Default Control Strip selectors:
//
case sdevInitModule: // check environs, allocate globals
result = sdevInit(statusPort);
break;
case sdevCloseModule: // release my memory
sdevClose((MyGlobalHandle) params, statusPort);
break;
case sdevFeatures: // let the strip track the mouse down
result = (**(MyGlobalHandle) params).currentFeatures;
break;
case sdevGetDisplayWidth: // inform the strip how much space we need
result = kTriangleWidth;
if ((**(MyGlobalHandle) params).useLargeIcon)
result += kLargeIconWidth + ((unsigned long)kLargeIconWidth << 16);
else
result += kSmallIconWidth;
break;
case sdevPeriodicTickle: // never called by Extensions Strip because we
{ // returned the sdevDontPeriodicTickle bit.
Rect viewRect = *statusRect;
// update the draggable box upon each idle cycle in case the user
// shrunk the Control Strip bar so that we are not visible, but our
// old position still is because the end of the bar is there.
viewRect.right -= kTriangleWidth;
(**(MyGlobalHandle) params).myBox = viewRect;
break;
}
case sdevDrawStatus: // draw my icon and arrow pict
sdevDraw((MyGlobalHandle) params, statusRect, statusPort);
break;
case sdevMouseClick: // the mouse was clicked & released in my button
result = sdevClick((MyGlobalHandle) params, statusRect, statusPort);
break;
case sdevSaveSettings: // no settings in this module
break;
case sdevShowBalloonHelp: // we have a custom ballon help string
{
Str255 helpString;
SBGetDetachedIndString(helpString, (**(MyGlobalHandle) params).myStrings, kHelpStringIndex);
SBShowHelpString(statusRect, helpString);
break;
}
//
// Extensions Strip specific selectors:
// Note that we check for the presence of ES just in case...
//
case sdevInAppContext: // we are inside Extensions Strip's context so
// is is safe to send Apple Events from here.
{
ProcessSerialNumber finderPSN;
ProcessInfoRec infoRec;
#define kFinderType 'FNDR'
#define kSysCreator 'MACS'
if ((**(MyGlobalHandle) params).hasExtensionsStrip) {
infoRec.processInfoLength = sizeof(ProcessInfoRec);
infoRec.processName = nil; // no name wanted processName;
infoRec.processAppSpec = nil; // no spec wanted &procSpec;
if (FindAProcess(kFinderType, kSysCreator, &finderPSN, &infoRec) == noErr)
QuitProcess(finderPSN, FALSE); // FALSE because we don't HAVE to use
// _SBSimpleAESend here
}
break;
}
case sdevInterceptedEvent: // a chance to look at and modify the current event
{
EventRecord *theEvent;
if ((**(MyGlobalHandle) params).hasExtensionsStrip) {
// for demonstration's purpose, we'll intercept command + *
// (* on the keypad only since cmd-shift-8 is an FKEY combo that
// is intercepted by the System.)
theEvent = SBGetCurrentEvent();
// we can assume a keydown since our mask filters out the rest.
// if (theEvent->what == keyDown)
if (theEvent->modifiers & cmdKey) {
switch (theEvent->message & charCodeMask)
{
case '*':
SysBeep(0);
theEvent->what = nullEvent; // don't pass on the event
break;
default:
break;
}
}
}
break;
}
case sdevDragAccept: // let Extensions Strip know if we won't handle the drag
if ((**(MyGlobalHandle) params).hasExtensionsStrip &&
!(**(MyGlobalHandle) params).canAcceptDrag)
result = 1; // we don't accept the drag
break;
case sdevEventMask: // let Extensions Strip know we want key down events
if ((**(MyGlobalHandle) params).hasExtensionsStrip)
result = keyDownMask; // our GNE style event mask
break;
}
return (result);
}
/******************************************************************************
sdevClick: handle a click in our status rect
******************************************************************************/
long sdevClick(MyGlobalHandle globH, const Rect *statusRect, WindowRef statusPort)
{
short menuID;
MenuHandle menuH = (**globH).myMenuH; // local copy to save deferencing
long result = 0L;
char itemMark;
short theBit;
// reflect the current features in th popup menu
itemMark = ((**globH).currentFeatures & (1L<<sdevWantMouseClicks)) ? sdevMenuItemMark : noMark;
SetItemMark(menuH, kHiliteClicks, itemMark);
itemMark = ((**globH).currentFeatures & (1L<<sdevHasCustomHelp)) ? sdevMenuItemMark : noMark;
SetItemMark(menuH, kCustomBalloons, itemMark);
itemMark = ((**globH).currentFeatures & (1L<<sdevInterceptAllEvents)) ? sdevMenuItemMark : noMark;
SetItemMark(menuH, kCheckKeyDowns, itemMark);
itemMark = ((**globH).useLargeIcon) ? sdevMenuItemMark : noMark;
SetItemMark(menuH, kUseLargeIcon, itemMark);
itemMark = ((**globH).currentFeatures & (1L<<sdevHasDragHandlers)) ? sdevMenuItemMark : noMark;
SetItemMark(menuH, kUseDragNDrop, itemMark);
// disable what COntrol/Desktop Strip doesn't support
if (!(**globH).hasExtensionsStrip) {
DisableItem(menuH, kSafeFinderQuit2);
SetItemMark(menuH, kCheckKeyDowns, noMark);
}
// show our popup menu
menuID = SBTrackPopupMenu(statusRect, menuH);
switch (menuID){
case kBeepIfPPC:
#ifdef powerc
SysBeep(0);
#endif
break;
case kHiliteClicks:
theBit = sdevWantMouseClicks;
// pass on
case kCustomBalloons:
if (menuID == kCustomBalloons)
theBit = sdevHasCustomHelp;
// pass on
case kCheckKeyDowns:
if (menuID == kCheckKeyDowns)
theBit = sdevInterceptAllEvents;
// pass on
case kUseDragNDrop:
if ((**globH).hasExtensionsStrip) {
if (menuID == kUseDragNDrop) {
theBit = sdevHasDragHandlers;
// Install/remove handlers for fun. We can also now
// unlock our code, all for demonstration purposes.
if ((**globH).currentFeatures & (1L<<sdevHasDragHandlers)) {
(**globH).currentFeatures -= (1L<<sdevKeepModuleLocked);
RemoveDragHandlers(statusPort, globH);
DisableItem(menuH, kDragFiles);
DisableItem(menuH, kDragTextClippings);
} else {
(**globH).currentFeatures += (1L<<sdevKeepModuleLocked);
InstallDragHandlers(statusPort, globH);
EnableItem(menuH, kDragFiles);
EnableItem(menuH, kDragTextClippings);
}
}
// handle the passed bit
if ((**globH).currentFeatures & (1L<<theBit))
(**globH).currentFeatures -= (1L<<theBit);
else
(**globH).currentFeatures += (1L<<theBit);
result = (1L<<sdevFeaturesChange); // request a sdevFeatures call
}
break;
case kUseLargeIcon:
(**globH).useLargeIcon = !(**globH).useLargeIcon;
// request to be asked our dimensions again
result = (1L<<sdevResizeDisplay);
break;
case kDragFiles:
(**globH).acceptFiles = !(**globH).acceptFiles;
itemMark = (**globH).acceptFiles ? sdevMenuItemMark : noMark;
SetItemMark(menuH, kDragFiles, itemMark);
break;
case kDragTextClippings:
(**globH).acceptText = !(**globH).acceptText;
itemMark = (**globH).acceptText ? sdevMenuItemMark : noMark;
SetItemMark(menuH, kDragTextClippings, itemMark);
break;
case kSafeFinderQuit1: {
ProcessSerialNumber finderPSN;
ProcessInfoRec infoRec;
infoRec.processInfoLength = sizeof(ProcessInfoRec);
infoRec.processName = nil; // no name wanted processName;
infoRec.processAppSpec = nil; // no spec wanted &procSpec;
if (FindAProcess(kFinderType, kSysCreator, &finderPSN, &infoRec) == noErr)
QuitProcess(finderPSN, (**globH).hasExtensionsStrip);
break;
}
case kSafeFinderQuit2:
// request sdevInAppContext to be called once within Extensions Strip's context
result = (1L<<sdevQueueModule);
break;
case kCloseDown:
result = (1L<<sdevCloseNow);
break;
} //end switch
return(result);
}
/******************************************************************************
sdevInit: allocate memory for our globals and init our globals
******************************************************************************/
long sdevInit(WindowRef statusPort)
{
MyGlobalHandle globH;
//
// get some memory
//
globH = (MyGlobalHandle) NewHandleClear(sizeof(MyGlobals));
if (!globH)
goto exit;
//
// temporarily lock our global handle because we pass pointers of it to toolbox
// functions. If I wanted to be really cool I'd load all the handles into local
// variables to remove this need, as well as the repetitive double deferencing...
//
HLock((Handle)globH);
//
// get our icon suite
//
if (SBGetDetachIconSuite(&(**globH).iconSuite, rIconSuiteId, svAllSmallData) != noErr) goto exit;
//
// get our string list
//
(**globH).myStrings = GetResource('STR#', rMyStringsID);
if (!(**globH).myStrings) goto exit;
DetachResource((**globH).myStrings);
//
// get our popup menu
//
(**globH).myMenuH = GetMenu(rPopupMenuID);
if (!(**globH).myMenuH) goto exit;
DetachResource((Handle)(**globH).myMenuH);
//
// get our arrow picture
//
(**globH).myArrowPict = GetPicture(rArrowPictID);
if (!(**globH).myArrowPict) goto exit;
DetachResource((Handle)(**globH).myArrowPict);
//
// setup our initial features
//
(**globH).currentFeatures = (
(1L<<sdevWantMouseClicks) // we handle mouse down
| (1L<<sdevDontAutoTrack) // we track the mouse, too
| (1L<<sdevHasCustomHelp) // custom help string
| (1L<<sdevKeepModuleLocked) // I need to be locked
// for drag-n-drop.
);
//
// determine if Extensions Strip is running.
// If so, get my reference number and setup ES specific feature flags
//
(**globH).hasExtensionsStrip = HasExtensionsStrip();
if ((**globH).hasExtensionsStrip)
{
(**globH).myReferenceNum = SBGetMyReferenceNum();
(**globH).currentFeatures +=
(
(1L<<sdevHasDragHandlers) // flag that we have drag handlers
| (1L<<sdevDontPeriodicTickle) // we don't need any idle time
| (1L<<sdevInterceptAllEvents) // get all events under Extensions Strip
);
}
//
// setup the drag stuff
//
InstallDragHandlers(statusPort, globH);
(**globH).acceptFiles = true;
SetItemMark((**globH).myMenuH, kDragFiles, sdevMenuItemMark);
//
// set my handle free and return its value
//
HUnlock((Handle)globH);
return ((long) globH);
//
// did not get any memory, don't install
//
exit:
return (-1L);
}
/******************************************************************************
sdevClose: free memory for our globals
******************************************************************************/
void sdevClose(MyGlobalHandle globH, WindowRef statusPort)
{
// useful macros:
#define myDisposeHandle(h)¥
if ((h) != nil)¥
DisposeHandle((Handle) (h))
#define myDisposeIconSuite(h, p1)¥
if ((h) != nil)¥
DisposeIconSuite(h, p1)
// dispose of everything:
if (globH){
myDisposeIconSuite((**globH).iconSuite, true);
myDisposeHandle((**globH).myMenuH);
myDisposeHandle((**globH).myStrings);
myDisposeHandle((**globH).myArrowPict);
RemoveDragHandlers(statusPort, globH);
DisposeHandle((Handle) globH);
}
}
/******************************************************************************
sdevDraw: draw our icon and arrow pict
******************************************************************************/
void sdevDraw(MyGlobalHandle globH, Rect *statusRect, WindowRef statusPort)
{
Rect viewRect = *statusRect;
short arrowHeight = 0;
PicHandle myArrowPict = (**globH).myArrowPict; // local copy to save deferencing
//
// update the drag area (only required for Control/Desktop Strip)
//
viewRect.right -= kTriangleWidth;
(**globH).myBox = viewRect;
//
// Draw our icon
//
DrawMyIcon(globH, false);
//
// Draw our right-arrow pict to show that we have a popup menu
//
if (myArrowPict){
arrowHeight = height((*myArrowPict)->picFrame);
viewRect.left = viewRect.right;
viewRect.right += width((*myArrowPict)->picFrame);
viewRect.top += ((height(viewRect) - arrowHeight) >> 1);
viewRect.bottom = viewRect.top + arrowHeight;
DrawPicture(myArrowPict, &viewRect);
}
}
#pragma mark -
/******************************************************************************
HasDragMgr: determine if the Drag Manager exists, and supports floaters
******************************************************************************/
Boolean HasDragMgr(void)
{
long gestaltResponse;
return( (Gestalt(gestaltDragMgrAttr, &gestaltResponse) == noErr) &&
(gestaltResponse & (1L << gestaltDragMgrPresent)) &&
(gestaltResponse & (1L << gestaltDragMgrFloatingWind)) );
}
/******************************************************************************
InstallDragHandlers: install & create everything having to do with drag handlers
******************************************************************************/
void InstallDragHandlers(WindowRef statusPort, MyGlobalHandle globH)
{
// local copies
DragTrackingHandlerUPP myTrackingUPP;
DragReceiveHandlerUPP myReceiveUPP;
if (HasDragMgr()) {
myTrackingUPP = NewDragTrackingHandlerProc(MyTrackingHandler);
myReceiveUPP = NewDragReceiveHandlerProc(MyReceiveDropHandler);
if (myTrackingUPP && myReceiveUPP) { // got UPPs successfully
InstallTrackingHandler(myTrackingUPP, statusPort, (void*) globH);
InstallReceiveHandler(myReceiveUPP, statusPort, (void*) globH);
}
(**globH).myTrackingUPP = myTrackingUPP;
(**globH).myReceiveUPP = myReceiveUPP;
} else {
// disable the drag-related menu items
// (doesn't move memory)
DisableItem((**globH).myMenuH, kUseDragNDrop);
DisableItem((**globH).myMenuH, kDragFiles);
DisableItem((**globH).myMenuH, kDragTextClippings);
}
}
/******************************************************************************
RemoveDragHandlers: remove & dispose everything having to do with drag handlers
******************************************************************************/
void RemoveDragHandlers(WindowRef statusPort, MyGlobalHandle globH)
{
// local copies
DragTrackingHandlerUPP myTrackingUPP = (**globH).myTrackingUPP;
DragReceiveHandlerUPP myReceiveUPP = (**globH).myReceiveUPP;
if (myTrackingUPP) {
RemoveTrackingHandler(myTrackingUPP, statusPort);
DisposeRoutineDescriptor(myTrackingUPP);
(**globH).myTrackingUPP = 0L;
}
if (myReceiveUPP) {
RemoveReceiveHandler(myReceiveUPP, statusPort);
DisposeRoutineDescriptor(myReceiveUPP);
(**globH).myReceiveUPP = 0L;
}
}
/******************************************************************************
HasExtensionsStrip: determine if Extensions Strip is installed and running
******************************************************************************/
Boolean HasExtensionsStrip(void)
{
long gestaltResponse;
return( (Gestalt(gestaltExtensionsStripAttr, &gestaltResponse) == noErr) &&
(gestaltResponse & (1L << gestaltExtensionsStripExists)) );
}
#pragma mark -
/******************************************************************************
FindAProcess: run through the process list looking for the indicated program
******************************************************************************/
OSErr FindAProcess(OSType typeToFind, OSType creatorToFind,
ProcessSerialNumberPtr processSN,
ProcessInfoRecPtr infoRecToFill)
{
OSErr myErr = noErr;
processSN->lowLongOfPSN = kNoProcess;
processSN->highLongOfPSN = 0;
do
{
myErr = GetNextProcess(processSN);
if (myErr == noErr)
GetProcessInformation(processSN, infoRecToFill);
}
while ( (myErr == noErr) && ((infoRecToFill->processSignature != creatorToFind) ||
(infoRecToFill->processType != typeToFind)) );
return(myErr);
}
/******************************************************************************
QuitProcess: Send a quit event to the specified process. If you are using the
program Extensions Strip the event will be sent safely from within
its Apple Event aware context.
******************************************************************************/
void QuitProcess (ProcessSerialNumber PSN, Boolean hasExtensionsStrip)
{ AEAddressDesc applicationAddress;
AppleEvent theEvent, returnEvent;
OSErr err;
AECreateDesc(typeProcessSerialNumber, &PSN, sizeof(ProcessSerialNumber), &applicationAddress);
AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &applicationAddress,
kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
AEDisposeDesc(&applicationAddress);
if (hasExtensionsStrip) {
err = SBSimpleAESend(&theEvent);
} else {
err = AESend(&theEvent, &returnEvent,
kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
kAENormalPriority,
kAEDefaultTimeout, nil, nil);
AEDisposeDesc(&returnEvent);
}
if (err) {
// error handling goes here
SysBeep(0);
}
AEDisposeDesc(&theEvent);
}
/******************************************************************************
MouseInMyBounds: mouse is over my total clickable area
******************************************************************************/
static Boolean MouseInMyBounds(MyGlobalHandle globH, WindowRef win,
DragReference theDrag)
{
Boolean result = false;
Point theMouse;
Rect hotBounds;
if (GetDragMouse(theDrag, &theMouse, 0L) == noErr) {
GlobalToLocal(&theMouse);
if ((**globH).hasExtensionsStrip)
SBGetTotalModuleBounds(&hotBounds, win, (**globH).myReferenceNum);
else
hotBounds = (**globH).myBox;
result = PtInRect(theMouse, &hotBounds);
}
return(result);
}
void DrawMyIcon(MyGlobalHandle globH, Boolean selected)
{
Rect viewRect;
if ((**globH).iconSuite)
{
// Get our icon's area
if ((**globH).hasExtensionsStrip) {
SBGetModuleBounds(&viewRect, (**globH).myReferenceNum);
viewRect.right -= kTriangleWidth;
} else
viewRect = (**globH).myBox;
// Draw our icon
PlotIconSuite(&viewRect, atNone, selected ? ttSelected : ttNone,
(**globH).iconSuite);
}
}
/******************************************************************************
MyTrackingHandler
******************************************************************************/
pascal OSErr MyTrackingHandler(short message, WindowRef win, void *handlerRefCon,
DragReference theDrag)
{
MyGlobalHandle globH = (MyGlobalHandle) handlerRefCon;
ItemReference theItem;
FlavorType theType;
unsigned short count, index, numFlavors, i;
switch (message)
{
case dragTrackingEnterHandler:
// do special global initialization here
break;
case dragTrackingEnterWindow:
// determine if we can support at least one of the drag items
(**globH).canAcceptDrag = false; // default to rejection
if (CountDragItems(theDrag, &count) == noErr)
{
for (index = 1; index <= count; index++) // check all the items
{
if ((GetDragItemReferenceNumber(theDrag, index, &theItem) == noErr) &&
(CountDragItemFlavors(theDrag, theItem, &numFlavors) == noErr)) {
for (i = 1; i <= numFlavors; i++) // check all the flavors
{
if ((GetFlavorType(theDrag, theItem, i, &theType) == noErr) &&
(((**globH).acceptFiles ? (theType == flavorTypeHFS) : 0) ||
((**globH).acceptText ? (theType == 'TEXT') : 0)))
{
(**globH).canAcceptDrag = true; // I like this flavor
}
}
}
}
}
break;
case dragTrackingInWindow:
// check if the mouse is over me
if ((**globH).canAcceptDrag)
if ((**globH).hasEntered != MouseInMyBounds(globH, win, theDrag))
{
(**globH).hasEntered = !(**globH).hasEntered;
DrawMyIcon(globH, (**globH).hasEntered);
}
break;
case dragTrackingLeaveWindow:
// if dragTrackingInWindow didn't handle the mouse leaving our area, do it here.
if ((**globH).hasEntered)
{
(**globH).hasEntered = false;
DrawMyIcon(globH, false);
}
break;
case dragTrackingLeaveHandler:
break;
}
return((**globH).canAcceptDrag ? noErr : dragNotAcceptedErr);
}
/******************************************************************************
MyReceiveDropHandler
******************************************************************************/
pascal OSErr MyReceiveDropHandler(WindowRef win, void *handlerRefCon,
DragReference theDrag)
{
MyGlobalHandle globH = (MyGlobalHandle) handlerRefCon;
OSErr result = dragNotAcceptedErr; // default to cancel (do zoom-back animation)
if ((**globH).hasEntered)
{
//
// process the drag here:
//
SysBeep(0);
//
result = noErr; // accept the drag (no zoom-back animation)
}
return(result);
}